from rest_framework import serializers
from utils.exception import OrderException
import uuid

from . import models
from libs.al_pay import alipay, gateway
from django.conf import settings


class PayOrderSerializer(serializers.ModelSerializer):
    courses = serializers.PrimaryKeyRelatedField(queryset=models.Course.objects.all(), many=True, write_only=True)

    class Meta:
        model = models.Order
        fields = ['subject', 'total_amount', 'pay_type', 'courses']
        extra_kwargs = {
            'subject': {'required': True},
            'total_amount': {'required': True},
            'pay_type': {'required': True},
        }

    def _check_price(self, attrs):
        courses = attrs.get('courses')
        total_price = 0
        for course in courses:
            total_price += course.price
        if not total_price == attrs.get('total_amount'):
            raise OrderException(detail='总金额不一致')

    def _get_order_no(self):
        order_no = str(uuid.uuid4())
        return order_no.replace('-', '')

    def _get_user(self):
        user = self.context['request'].user
        return user

    def _get_pay_url(self, attrs, order_no):
        order_string = alipay.api_alipay_trade_page_pay(
            out_trade_no=order_no,
            total_amount=float(attrs.get('total_amount')),
            subject=attrs.get('subject'),
            return_url=settings.RETURN_URL,
            notify_url=settings.NOTIFY_URL)
        return gateway + order_string

    def _pre_create(self, attrs, user, order_no):
        attrs['order_status'] = 0
        attrs['user'] = user
        attrs['out_trade_no'] = order_no

    def validate(self, attrs):
        # 1) 订单总价校验
        self._check_price(attrs)
        # 2) 生成订单号
        order_no = self._get_order_no()
        # 3) 支付用户：request.user
        user = self._get_user()
        # 4) 支付链接生成
        pay_url = self._get_pay_url(attrs, order_no)
        self.context['pay_url'] = pay_url
        # 5) 入库重写create
        self._pre_create(attrs, user, order_no)
        return attrs

    def create(self, validated_data):
        courses = validated_data.pop('courses')
        order = models.Order.objects.create(**validated_data)
        for course in courses:
            models.OrderDetail.objects.create(order=order, course=course, price=course.price, real_price=course.price)

        return order
